#include <co_async/and_then.hpp>
#include <co_async/task.hpp>
#include <co_async/timer_loop.hpp>
#include <co_async/when_all.hpp>
#include <co_async/when_any.hpp>
#include <sys/epoll.h>
#include <fcntl.h>
#include <cstring>
#include <cerrno>

/**

    bilibili: BV18t421G7fD 0:00~22:31
*/

using namespace std::chrono_literals;

int main() {
    // 打开标准输入，并设置为非阻塞模式
    // 这样当你read时没有数据，会直接返回EWOULDBLOCK错误
    int attr = 1;
    ioctl(0, FIONBIO, &attr);

    // 创建epoll句柄 异步控制器
    int epfd = epoll_create1(0);
    if (epfd == -1) {
        perror("epoll_create1");
        return 1;
    }

    // 创建异步监听器（目标：0号输入流也就是标准输入，事件：有输入数据）
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = 0; // 0号代表标准输入。我们不要使用语言的库，而去使用操作系统标准库来完成。
    epoll_ctl(epfd, EPOLL_CTL_ADD, fileno(stdin), &event);

    // 开始异步读取输入流
    while (true) {
        struct epoll_event ebuf[10];
        int res = epoll_wait(epfd, ebuf, 10, 1000);  // -1代表一直等，1000代表1秒。这样设置后，1s就超时

        if (res == -1) {
            debug(), "epoll wait err";
        }

        if(res==0){
            debug(), "epoll超时, 1秒内没有等到任何回应。";
        }
        for (int i = 0; i < res; i++) {
            debug(), "stdin输入事件";
            int fd = (int)ebuf[i].data.fd;
            char c;
            while (true) {
                int len = read(fd, &c, 1);
                if(len<=0){
                    if (errno == EWOULDBLOCK){
                        // 没数据了就回到等待状态。
                        debug(), "前面的区域以后再来探索吧";
                        break;
                    }
                    debug(), "read出错了", strerror(errno);
                    // break;
                }
                debug(), c;
            }
        }
        // debug(), "等到了stdin的输入事件";
    }
    return 0;
}
